<style lang="scss" scoped>
.list-move {
  transition: all 0.5s ease;
}
</style>

<template>
  <div class="root-flex-page p-2">
    <div
      class="mb-3 flex flex-shrink-0 items-center border-b-2 border-blue-400 pb-2 text-2xl font-bold text-blue-500"
    >
      <Icon
        v-if="ISocket?.status === 'OPEN'"
        name="majesticons:status-online-line"
        color="#1989fa"
      />
      <Icon
        v-else-if="ISocket?.status === 'CONNECTING'"
        name="line-md:loading-alt-loop"
        color="#1989fa"
      />
      <Icon v-else name="majesticons:status-offline-line" color="#ee1d6a" />

      <span style="-webkit-app-region: drag" class="ml-1 select-none truncate">
        排队列表
      </span>
      <Icon class="ml-1" name="arcticons:genshin-impact" />

      <div class="ml-auto flex gap-2">
        <button
          class="btn-secondary btn-sm btn"
          @click="router.push({ name: 'keke-code' })"
        >
          扫码
        </button>
        <button class="btn-secondary btn-sm btn" @click="init">刷新</button>
        <button class="btn-primary btn-sm btn" @click="onClear">清空</button>
        <button
          class="btn-primary btn-sm btn"
          @click="
            () => {
              editItem = {}
              editOpen = true
            }
          "
        >
          排队
        </button>
      </div>
    </div>

    <div class="flex-1 overflow-y-scroll">
      <VueDraggableNext
        v-model="list"
        ghost-class="bg-blue-300"
        @change="changeSort"
      >
        <transition-group
          :css="false"
          @enter="onEnter"
          @leave="onLeave"
          name="list"
        >
          <div
            @click="openDetail(item)"
            v-for="(item, index) in list"
            :key="item.name"
            :data-index="index"
            class="items-cente box-content flex h-6 cursor-pointer select-none px-2 py-2"
          >
            <span
              class="mr-2 w-6 flex-shrink-0 rounded-full bg-blue-300 text-center text-white shadow"
            >
              {{ index + 1 }}
            </span>
            <span class="truncate font-bold tracking-widest text-blue-400">
              {{ item.name }}
            </span>
            <button
              class="btn-xs btn ml-auto text-green-400"
              @click.stop="onOver(item, index)"
            >
              完成
            </button>
            <button
              class="btn-xs btn ml-2 text-red-400"
              @click.stop="onDelete(item, index)"
            >
              删除
            </button>
          </div>
        </transition-group>
      </VueDraggableNext>
    </div>
    <div class="flex flex-shrink-0 items-center">
      <van-pagination
        v-if="total > pageInfo.size"
        class="w-full"
        :show-prev-button="false"
        :show-next-button="false"
        v-model="pageInfo.page"
        :items-per-page="pageInfo.size"
        @change="init"
        :total-items="total"
        force-ellipses
      />
      <div
        class="ml-auto flex h-9 flex-shrink-0 cursor-move items-center rounded bg-blue-50 px-4 shadow"
        style="-webkit-app-region: drag"
      >
        {{ total ? `共 ${total} 人` : '暂时无人' }}
      </div>
    </div>

    <van-overlay
      :show="editOpen"
      :lock-scroll="false"
      @click="editOpen = false"
    >
      <div
        class="absolute bottom-0 h-3/4 w-full rounded-t-xl bg-white"
        @click.stop
      >
        <van-form
          ref="FormRef"
          label-align="top"
          class="flex h-full flex-col p-2"
        >
          <p class="mb-2 font-bold tracking-widest">修改/增加排队信息</p>
          <div class="flex-1 overflow-y-scroll">
            <van-field
              v-model="editItem.name"
              label="b站昵称"
              placeholder="b站昵称"
            />
            <van-field
              v-model="editItem.account"
              label="游戏账号"
              placeholder="游戏账号"
            />
            <van-field v-model="editItem.uid" label="UID" placeholder="UID" />

            <van-field
              v-model="editItem.remark"
              rows="3"
              autosize
              label="备注/留言"
              type="textarea"
              maxlength="252"
              placeholder="请输入留言"
              show-word-limit
            />
          </div>
          <div class="mt-auto flex w-full flex-shrink-0 gap-4">
            <button class="btn-warning btn flex-1" @click="editOpen = false">
              取消
            </button>
            <button class="btn-primary btn flex-1" @click="onSubmit">
              确定
            </button>
          </div>
        </van-form>
      </div>
    </van-overlay>
  </div>
</template>

<script lang="ts" setup>
import {
  getQueueList,
  getQueueDetail,
  addQueue,
  changeQueue,
  clearQueue,
  sortQueue,
  type IQueueUser,
} from '~/api'
import { VueDraggableNext } from 'vue-draggable-next'
import { type FormInstance } from 'vant'
import { useIpcRendererOn } from '@vueuse/electron'

const { $gsap: gsap } = useNuxtApp()
interface IData {
  list: IQueueUser[]
  total: number

  editOpen: boolean
  editItem: Partial<IQueueUser>
  pageInfo: {
    page: number
    size: number
  }
}

const { key } = useGlobalState()
const ISocket = ref<any>()
const router = useRouter()
const FormRef = ref<FormInstance>()
const WS_URL = (import.meta.env.VITE_BASW_WS_API as string) + '/queue'
const data = reactive<IData>({
  list: [],
  total: 0,
  editOpen: false,
  editItem: {},
  pageInfo: {
    page: 1,
    size: CONF_DEFINE_PAGESIZE,
  },
})

const onEnter = (el: any, done: () => void) => {
  gsap.from(el, {
    opacity: 0,
    y: 100,
    clipPath: 'inset(0 100% 0 0%)',
    delay: el.dataset.index * 0.15,
    onComplete: done,
  })
}

const onLeave = (el: any, done: () => void) => {
  const animate = gsap.timeline()
  animate
    .to(el, {
      opacity: 0,
      clipPath: 'inset(0 100% 0 0%)',
    })
    .to(el, {
      height: 0,
      paddingTop: 0,
      paddingBottom: 0,
      onComplete: done,
    })
}

async function openDetail({ id }: { id: number }) {
  const editItem = await getQueueDetail(id)
  const editOpen = true
  Object.assign(data, { editItem, editOpen })
}

async function onDelete({ id, name }: IQueueUser, index: number) {
  await showConfirmDialog({
    title: '提示',
    message: `删除“ ${name} ”的排队信息？`,
  })
  await changeQueue({ id, state: 9 })
  data.list.splice(index, 1)
}

async function onClear() {
  await showConfirmDialog({
    title: '清空？',
  })
  await clearQueue()
  Object.assign(data, { list: [], total: 0 })
}

async function onOver({ id }: IQueueUser, index: number) {
  await showConfirmDialog({
    title: '完成？',
  })
  await changeQueue({ id, state: 0 })
  data.list.splice(index, 1)
}

async function onSubmit() {
  await FormRef.value?.validate()
  const Item = useCloneDeep(data.editItem as IQueueUser)
  if (!Item.id) {
    await init()
    Item.sort = data.list.length
  }
  const { id, type } = await addQueue(Item)
  showSuccessToast(`${type}成功`)
  Item.id = id
  if (type === '添加') {
    if (data.total < CONF_DEFINE_PAGESIZE) {
      data.list.push(Item)
    }
    data.total += 1
  } else {
    const sourceItem = data.list.find(({ id: sid }) => sid === id) as IQueueUser
    Object.assign(sourceItem, Item)
  }
  data.editOpen = false
}

async function changeSort() {
  const resData = data.list.map(({ id }, sort) => ({ id, sort }))
  await sortQueue(resData)
}

async function init() {
  const { list, total } = await getQueueList(data.pageInfo)
  Object.assign(data, { list, total })
}

onBeforeMount(() => {
  init()
})

onMounted(() => {
  ISocket.value = useWebSocket(WS_URL, {
    onConnected: (ws) => {
      ws.send(key.value)
    },
    onMessage: (ws, message) => {
      const { list, total } = JSON.parse(message.data)
      data.total = total
      showToast('叮咚~')
      if (data.pageInfo.page === 1) {
        Object.assign(data, { list })
      }
    },
    autoReconnect: {
      retries: 10,
      delay: 1000,
      onFailed() {
        showFailToast('ws:连接自动重连失败！')
      },
    },
  })
})
const { list, editOpen, editItem, pageInfo, total } = { ...toRefs(data) }

try {
  useIpcRendererOn('reload', init)
} catch (error) {
  console.log('Likely Not In Electron')
}
</script>
